/*
 * IteradorIndice.cpp
 *
 *  Created on: 23/10/2011
 *      Author: diego
 */

#include "IteradorIndice.h"

IteradorIndice::IteradorIndice(string prefijo) {
	Configuracion* conf = Configuracion::getConf(PATH_CONF);
	string path_indice = conf->path_indice() + prefijo + "_indice.dat";
	this->indice = new ifstream(path_indice.c_str(), ios::in | ios::binary);

	string path_docs = conf->path_indice() + prefijo + "_docs.dat";
	this->docs = new BitReader(path_docs.c_str());

	string path_terminos = conf->path_indice() + prefijo + "_terminos.dat";
	this->terminos = new ifstream(path_terminos.c_str(), ios::in);


	this->paso = 1;

	string path_header = conf->path_indice() + prefijo + "_header.dat";
	this->header = new ifstream(path_header.c_str(), ios::in | ios::binary);

	reg_header_indice header;
	// leo el encabezado donde me dice la cantidad de registros del archivo
	this->header->read(reinterpret_cast<char *>(&header), sizeof(reg_header_indice));
	this->cant_registros = header.cant_registros;
	this->header->close();
	this->pos_actual = 0;


	this->termino_actual = NULL;
	this->termino_anterior = NULL;

}

IteradorIndice::IteradorIndice() {
	Configuracion* conf = Configuracion::getConf(PATH_CONF);
	string path_indice = conf->path_indice() + "indice.dat";
	this->indice = new ifstream(path_indice.c_str(), ios::in | ios::binary);

	string path_docs = conf->path_indice() + "docs.dat";
	this->docs = new BitReader(path_docs.c_str());

	string path_terminos = conf->path_indice() + "terminos.dat";
	this->terminos = new ifstream(path_terminos.c_str(), ios::in);

	this->paso = 1;

	string path_header = conf->path_indice() + "header.dat";
	this->header = new ifstream(path_header.c_str(), ios::in | ios::binary);

	reg_header_indice header;
	// leo el encabezado donde me dice la cantidad de registros del archivo
	this->header->read(reinterpret_cast<char *>(&header), sizeof(reg_header_indice));
	this->cant_registros = header.cant_registros;
	this->header->close();
	this->pos_actual = 0;

	this->termino_actual = NULL;
	this->termino_anterior = NULL;
}

int IteradorIndice::getCantTerminos(){
	return this->cant_registros;
}

bool IteradorIndice::tieneSiguiente(){
	return (this->cant_registros > this->pos_actual);
}
super_reg* IteradorIndice::proximoRegistro(){

	this->pos_actual++;

	super_reg* registro = new super_reg;
	reg_indice_fijo reg_indice, reg_indice_void;
	//reg_docs_variable reg_docs;
	unsigned int i;

	char *buffer;

	this->indice->read(reinterpret_cast<char *>(&reg_indice), sizeof(reg_indice_fijo));

	registro->frec_t = reg_indice.frec_t;
	registro->cant_docs = reg_indice.cant_docs;
//cout << "distintos: " << reg_indice.distintos << endl;
	buffer = new char[reg_indice.distintos];

	if (this->terminos->tellg() != reg_indice.offset_terminos){
		this->terminos->seekg(reg_indice.offset_terminos, ios::beg);
	}

	this->terminos->read(buffer, reg_indice.distintos);

	this->reconstruirTermino(reg_indice, buffer);

	delete buffer;

	registro->termino = string(this->termino_actual);

	//leo y reconstruyo los terminos siguientes para dar el paso
	for (i = 0; (i < this->paso - 1) && (!this->indice->eof()); i++){
		this->pos_actual++;
		this->indice->read(reinterpret_cast<char *>(&reg_indice_void), sizeof(reg_indice_fijo));

		buffer = new char[reg_indice_void.distintos];
		this->terminos->read(buffer, reg_indice_void.distintos);

		this->reconstruirTermino(reg_indice_void, buffer);

		delete buffer;
	}

	this->docs->posicionar(reg_indice.offset_docs);
	registro->lista = new Lista<reg_docs_variable*>();
	int doc_id = 0;

	reg_docs_variable* reg_docs;

	for (i = 0; i < reg_indice.cant_docs; i++){
		doc_id += deltaDecode(this->docs);
		reg_docs = new reg_docs_variable;
		reg_docs->doc_id = doc_id;
		reg_docs->frec = deltaDecode(this->docs);
		registro->lista->agregar(reg_docs);
	}

	return registro;
}

void IteradorIndice::reconstruirTermino(reg_indice_fijo reg, char* buffer){
	unsigned int i;
	if (this->termino_anterior != NULL){
		delete this->termino_anterior;
	}

	this->termino_anterior = this->termino_actual;
	this->termino_actual = new char[reg.repetidos + reg.distintos];

	if (this->termino_anterior != NULL){
		for (i = 0; i < reg.repetidos; i++){
			this->termino_actual[i] = this->termino_anterior[i];
		}
	}

	for (i = 0; i < reg.distintos; i++){
		this->termino_actual[reg.repetidos + i] = buffer[i];
	}

	if (this->termino_anterior != NULL){
		delete this->termino_anterior;
		this->termino_anterior = NULL;
	}
}


void IteradorIndice::setPaso(int p){
	if (p > 0){
		this->paso = p;
	}
}

int IteradorIndice::getPosicion(){
	return this->pos_actual;
}

void IteradorIndice::setPosicion(int pos){
	this->indice->seekg(pos * sizeof(reg_indice_fijo), ios::beg);


}

IteradorIndice::~IteradorIndice() {
	this->indice->close();
	delete this->indice;

	this->terminos->close();
	delete this->terminos;

	this->docs->cerrar();
	delete this->docs;

	delete this->header;
}

